package com.my.ry.redis;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.concurrent.Callable;

import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;


public class RedisCacheUtil implements Cache{

	private RedisTemplate<String, Object> redisTemplate;
	private String name;
	
	public RedisTemplate<String, Object> getRedisTemplate() {
		return this.redisTemplate;
	}
	
	/**
	 * 通过setter方式注入
	 * @param redisTemplate
	 */
	public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}
	
	public void setName(String name) {  
		this.name = name;    
	}  
	
	@Override
	public String getName() {
		return this.name;    
	}
	
	@Override
	public void clear() {
		redisTemplate.execute(new RedisCallback<String>() {

			@Override
			public String doInRedis(RedisConnection connection) throws DataAccessException {
				connection.flushDb();
				return "ok";
			}
		});
	}

	/**
	 * 删除key
	 */
	@Override
	public void evict(Object key) {
		final String keyf = key.toString();
		redisTemplate.execute(new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.del(keyf.getBytes());
			}
		});
	}

	/**
	 * 从缓存中获取key
	 */
	@Override
	public ValueWrapper get(Object arg0) {
		final String keyf =  arg0.toString();
		 Object object = null; 
		 object = this.redisTemplate.execute(new RedisCallback<Object>() {
			@Override
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				byte[] keys = keyf.getBytes();
				byte[] value = connection.get(keys);
				if (value == null) {
					return null;
				}
				
				return toObject(value);
			}
		});
		return (object != null ? new SimpleValueWrapper(object) : null);
	}

	@Override
	public <T> T get(Object arg0, Class<T> arg1) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public <T> T get(Object arg0, Callable<T> arg1) {
		// TODO Auto-generated method stub
		return null;
	}

	

	@Override
	public Object getNativeCache() {
		return this.redisTemplate;
	}

	/**
	 * 将一个新的key保存到缓存中
	 * 先拿到需要缓存key名称和对象，然后将其转成ByteArray
	 */
	@Override
	public void put(Object key, Object value) {
		final String keyf = key.toString();
		final Object valuef = value;
		final long liveTime = 86400;
		redisTemplate.execute(new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				byte[] keys = keyf.getBytes();
				byte[] valueb = toByteArray(valuef);
				connection.set(keys, valueb);
				// 设定过期时间
				if (liveTime > 0) {
					connection.expire(keys, liveTime);
				}
				return 1L;
			}
		});
	}

	@Override
	public ValueWrapper putIfAbsent(Object arg0, Object arg1) {
		// TODO Auto-generated method stub
		return null;
	}
	
	/**
	 * Object对象 转 byte数组
	 * @param obj
	 * @return
	 */
	private byte[] toByteArray(Object obj){
		byte[] bytes = null;
		
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		
		try {
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(obj);
			oos.flush();
			bytes = bos.toByteArray();
			oos.close();
			bos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return bytes;
	}
	
	/**
	 * byte数组 转 Object对象
	 * @param bytes
	 * @return
	 */
	private Object toObject(byte[] bytes) {
		Object object = null;
		try {
			ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
			ObjectInputStream ois = new ObjectInputStream(bis);
			object = ois.readObject();
			ois.close();
			bis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return object;
	}
}
